<?php

namespace app\admin\controller;

use app\common\controller\Backend;
use app\common\model\goods\Goods;
use app\common\model\goods\GoodsHouseStock;
use app\common\model\sales\Goods as sGoods;
use think\Db;
use think\Exception;

/**
 * 生产单
 *
 * @icon fa fa-circle-o
 */
class ProductionProcess extends Backend
{
    
    /**
     * ProductionProcess模型对象
     * @var \app\common\model\ProductionProcess
     */
    protected $model = null;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\common\model\ProductionProcess;

    }
    
    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */
    

    /**
     * 查看
     */
    public function index()
    {
        //当前是否为关联查询
        $this->relationSearch = false;
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if ($this->request->isAjax())
        {
            //如果发送的来源是Selectpage，则转发到Selectpage
            if ($this->request->request('keyField'))
            {
                return $this->selectpage();
            }
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
            $total = $this->model
                    
                    ->where($where)
                    ->order($sort, $order)
                    ->count();

            $list = $this->model
                    
                    ->where($where)
                    ->order($sort, $order)
                    ->limit($offset, $limit)
                    ->select();

            foreach ($list as $row) {
                $row->visible(['id','title','number','goods_num','consume_num','cost','operator','createtime','production_number','image']);
                
            }
            $list = collection($list)->toArray();
            $result = array("total" => $total, "rows" => $list);

            return json($result);
        }
        return $this->view->fetch();
    }
    public function seach(){
        $house_id = input('house_id/d',0);

        $this->assign('house_id',$house_id);
        return $this->view->fetch();
    }
    public function add()
    {
        if ($this->request->isPost()) {
            $params = input();
            //添加生产单 需要扣除商品物料
            //检查商品是否设置物料
            if (empty($params['cost'])){
               $this->error("先添加商品信息");
            }
            $storehouse_id = input('storehouse_id/d',0);
            $goodsIds = [];
            $vdata = [];

            $goods_num = 0;
            $consume_num = 0;
            $cost = 0;
            $production_log = [];

            foreach ($params['cost'] as $k=>$v){
                $goodsIds[] = $v['goods_id'];
                $vdata[] = [
                    'goods_id'=>$v['goods_id'],
                    'production_num'=>$v['goods_num'],
                ];
                $goods_num = bcadd($goods_num,$v['goods_num']);
            }

            $goods = Db::name("goods_material")->field("goods_id")->where("goods_id","in",$goodsIds)->group("goods_id")->select();
            foreach ($goodsIds as $val){
                $goodsTrue = false;
                foreach ($goods as $v){
                    if ($val == $v['goods_id']){
                        $goodsTrue =true;
                    }
                }
                if ($goodsTrue == false){
                    $this->error("商品".$val."未设置物料");
                }
            }

            //进入物料库存分析
            $goods = Db::name("goods_material")
                ->alias('m')
                ->field("m.*,goods.*,zax_goods_house_stock.stock,zax_goods_house_stock.weighting_cost")
                ->join("goods","m.material_id=goods.id")
                ->join("zax_goods_house_stock","m.material_id=zax_goods_house_stock.goods_id")
                ->where("m.goods_id","in",$goodsIds)
                ->where("zax_goods_house_stock.storehouse_id",$storehouse_id)
                ->select();

            $material = [];

            foreach ($vdata as $k=>$v){
                $issetGoods = false;
                foreach ($goods as $val){
                    if ($v['goods_id'] == $val['goods_id']){
                        //计算物料消耗
                        if (bcmul($v['production_num'],$val['material_num'])  > $val['stock']){
                            $this->error("商品".$val['goods_id']."库存不足");
                        }
                        $consume_num = bcadd($consume_num,bcmul($v['production_num'],$val['material_num']));

                        $cost = bcadd($cost,bcmul(bcmul($v['production_num'],$val['material_num']),$val['weighting_cost'],4),4);
                        $material[$val['goods_id']][] = [
                            'goods_id'=>$val['material_id'],
                            'production_num'=>$v['production_num'],
                            'material_num'=>$val['material_num'],
                            'cost'=>$val['weighting_cost'],
                            'all_cost'=>bcmul(bcmul($v['production_num'],$val['material_num']),$val['weighting_cost'],4),
                            'all_num'=>bcmul($v['production_num'],$val['material_num'])
                            ];
                        $vdata[$k]['process_cost'] = bcadd(isset($vdata[$k]['process_cost'])?$vdata[$k]['process_cost']:0,bcmul($val['weighting_cost'],$val['material_num'],4),4);
                        $issetGoods = true;
                    }
                }
                if ($issetGoods == false){
                    $this->error("商品".$v['goods_id']."物料库存不足");
                }
            }

            Db::startTrans();
            try {
                $group = Db::name('auth_group_access')->alias('a')->where(array('uid' => session('admin')['id']))->join('zax_auth_group g', 'a.group_id = g.id')->find();

                $num = Db::name("production_process")->where("createtime",">",strtotime(date("Y-m-d")))->count();
                //创建生产单
                $process = [
                    'title'=>$params['row']['title'],
                    'number'=>"SC-".createNumber($num),
                    'storehouse_id'=>$storehouse_id,
                    'goods_num'=>$goods_num,
                    'consume_num'=>$consume_num,
                    'cost'=>$cost,
                    'admin_id'=>session('admin')['id'],
                    'group_id'=>$group['id'],
                    'operator'=>session('admin')['username'],
                    'production_number'=>rand(100000,999999),
                    'image'=>$params['row']['image'],
                    'status'=>1,
                    'createtime'=>time()
                ];
                $process_id = Db::name("production_process")->insertGetId($process);
                //创建生产记录单

                foreach ($vdata as $k=>$v){
                    $materialBak = $material[$v['goods_id']];
                    $production_log[] = [
                        'production_id'=>$process_id,
                        'goods_id'=>$v['goods_id'],
                        'production_num'=>$v['production_num'],
                        'material'=>json_encode($materialBak),
                        'createtime'=>time()
                    ];
                }
                $res =  Db::name("production_log")->insertAll($production_log);
                if (empty($res)){
                    throw new Exception('添加生产资料失败');
                }
                //更新库存信息
                foreach ($vdata as $v){
                    $house = new GoodsHouseStock();
                    $res = $house->addstock($v['goods_id'],$storehouse_id,$v['production_num'],$v['process_cost']);
                    if(!$res){
                        throw new Exception('库存计算错误');
                    }
                }

                foreach ($material as $val){
                    foreach ($val as $v){
                        $house = new GoodsHouseStock();
                        $res = $house->reducestock($v['goods_id'],$storehouse_id,$v['all_num']);
                        if(!$res){
                            throw new Exception('库存计算错误');
                        }
                    }
                }
                Db::commit();
                return  array(
                    'code'=>1,
                    'msg'=>'添加成功',
                );
            }catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                $this->error($e->getMessage());
            }
        }
        return $this->view->fetch();
    }
    public function detail($ids = null){
        $row = Db::name("production_process")->find($ids);
        $goods = Db::name("production_log")->where([
            'production_id'=>$ids
        ])->alias('l')
            ->field("l.*,goods.title,goods.image,goods.unit,goods.specs,goods.place_origin,supplier_brands.name as brand")
            ->join("goods","l.goods_id=goods.id")
            ->join("supplier_brands","goods.brands_id=supplier_brands.id")
            ->select();
        $allNum = 0;
        $allCost = 0;
        foreach ($goods as $k=> $val){
            $material = json_decode($val['material'],true);
            $cost = 0;
            foreach ($material as $v){
                $cost = bcadd($cost,$v['all_cost'],4);
            }
            $goods[$k]['cost'] = $cost;
            $allNum = bcadd($allNum,$val['production_num']);
            $allCost = bcadd($allCost,$cost,4);
        }
        $this->assign('allCost',$allCost);
        $this->assign('allNum',$allNum);
        $this->assign('goods',$goods);
        $this->assign('row',$row);
        return $this->view->fetch();
    }
    public function getgood($ids = null){
        $house_id = input('house_id/d',0);
        if(empty($house_id)){
            $this->error('未选择仓库');
        }
        $ginfo  = Db::name("goods")->find($ids);
        if(empty($ginfo)){
            $this->error('无商品');
        }
        $gstock = Db::name("goods_house_stock")->where(array('goods_id'=>$ids,'storehouse_id'=>$house_id))->find();
        if (!empty($gstock)){
            $ginfo['new_cost'] = $gstock['new_cost'];
            $GoodsHouseStock = new GoodsHouseStock;
            $ginfo['xstock'] = $GoodsHouseStock->getfictstock($ginfo['id'],$house_id);
            $ginfo['stock'] = $GoodsHouseStock->getstock($ginfo['id'],$house_id);
        }else{
            $ginfo['new_cost'] = 0;
            $ginfo['xstock'] = 0;
            $ginfo['stock'] = 0;
        }


        return $ginfo;
    }
    public function cancelbill($ids = null){
        $row = $this->model->find($ids);
        if(!$row){
            $this->error('非法操作');
        }
        $reason = input('reason');
        if(empty($reason)){
            $this->error('理由必须填写');
        }
        if($row['status'] != 1){
            $this->error('状态异常');
        }


        $group = Db::name('auth_group_access')->alias('a')->where(array('uid'=>session('admin')['id']))->join('zax_auth_group g','a.group_id = g.id')->find();

        Db::startTrans();
        try {
            Db::name('cancel_bill')
                ->insert(array(
                    'reason' => $reason,
                    'source' => 13,
                    'admin_id' => session('admin')['id'],
                    'group_id' => $group['group_id'],
                    'company' => $group['name'],
                    'operator' => session('admin')['nickname'],
                    'controller' => 'productionProcess',
                    'source_id' => $row['id'],
                    'number' => isset($row['number']) ? $row['number'] : '',
                    'createtime' => time(),
                ));
            //审核记录
            Db::name('examine_log')->insert(array(
                'admin_id' => session('admin')['id'],
                'type' => 3,
                'createtime' => time(),
                'controller' => 'productionProcess',
                'source_id' => $ids,
                'source' => 13,
                'remark' => '生产单',
                'number' => isset($row['number']) ? $row['number'] : '',
            ));

           //库存回退//更新库存信息
            $goods = Db::name("production_log")->where(['production_id'=>$ids])->select();
            foreach ($goods as $val){
                $material = json_decode($val['material'],true);
                foreach ($material as $v) {
                    $house = new GoodsHouseStock();
                    $res = $house->addstock($v['goods_id'], $row['storehouse_id'], $v['production_num'], $v['cost']);
                    if (!$res) {
                        throw new Exception('库存计算错误');
                    }
                }
            }

            foreach ($goods as $val){
                $material = json_decode($val['material'],true);
                $cost = 0;
                foreach ($material as $v){
                    $cost = bcadd($cost,$v['all_cost'],4);
                }
                $house = new GoodsHouseStock();
                $res = $house->reducestock($val['goods_id'],$row['storehouse_id'],$v['production_num'],$cost);
                if(!$res){
                    throw new Exception('库存计算错误');
                }
            }
            //单据状态修改
            $res = $this->model->save(array('status' => 9), array('id' => $ids));
            if ($res) {
                Db::commit();
                return array(
                    'code'=>1,
                    'msg'=>'中止成功',
                );
            }
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            $this->error($e->getMessage());
        }
    }
}
